/* gftp2 - Request
 *
 * Author: Lingtao Pan <freeplant@gmail.com>
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifndef GFTP_REQUEST_H
#define GFTP_REQUEST_H

typedef struct _gftp_request gftp_request;

typedef void (*gftp_logging_func)		(gftp_logging_level level, 
                                         gftp_request * request, 
                                         const char *string, ...);

#define GFTP_ANONYMOUS_USER			"anonymous"
#define gftp_need_username(request)		((request)->need_username && ((request)->username == NULL || *(request)->username == '\0'))
#define gftp_need_password(request)		((request)->need_password && (request)->username != NULL && *(request)->username != '\0' && strcasecmp ((request)->username, GFTP_ANONYMOUS_USER) != 0 && ((request)->password == NULL || *(request)->password == '\0'))

#define GFTP_IS_CONNECTED(request)      ((request) != NULL && \
                                                 ((request)->datafd > 0 || \
                                                  (request)->cached || \
                                                  (request)->always_connected))


struct _gftp_request
{
    int protonum;  /* Current number of the protocol this is set to */
    char *hostname,     /* Hostname we will connect to */
         *username,     /* Username for host*/
         *password,     /* Password for host */
         *account,      /* Account for host (FTP only) */
         *directory,    /* Current working directory */
         *url_prefix,   /* URL Prefix (ex: ftp) */
         *last_ftp_response,      /* Last response from server */
         *last_dir_entry;         /* Last dir entry from server */
    size_t last_dir_entry_len;    /* Length of last_dir_entry */

    unsigned int port;        /* Port of remote site */

    int datafd,           /* Data connection */
        cachefd;          /* For the directory cache */
    int wakeup_main_thread[2];    /* FD that gets written to by the threads
                                   to wakeup the parent */

    /* One of these are used to lookup the IP address of the host we are
       connecting to */
#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
    struct addrinfo *hostp,
        *current_hostp;
#else
    struct hostent host, *hostp;
    int curhost;
#endif

    int ai_family;
    int server_type;      /* The type of server we are connected to.
                                   See GFTP_DIRTYPE_* above */
    unsigned int free_hostp : 1,      /* Should we free the hostp structure 
                                         in gftp_destroy_request() */
               use_proxy : 1,
               always_connected : 1,
               need_hostport : 1,
               need_username : 1,
               need_password : 1,
               use_cache : 1,           /* Enable or disable the cache */
               cached : 1,              /* Is this directory listing cached? */
               cancel : 1,      /* If a signal is received, should
                                   we cancel this operation */
               stopable : 1,
               running  : 1,
               refreshing : 1;

    off_t gotbytes;
 
    void *protocol_data;
   
    gftp_logging_func logging_function;
    void *user_data;

    int (*init)               (gftp_request * request);
    void (*copy_param_options)        (gftp_request * dest_request, 
                                       gftp_request * src_request);
    ssize_t (*read_function)      (gftp_request * request,
                                   void *ptr, 
                                   size_t size, 
                                   int fd );
    ssize_t (*write_function)     (gftp_request * request, 
                                   const char *ptr, 
                                   size_t size, 
                                   int fd);
    void (*destroy)           (gftp_request * request);
    int (*connect)            (gftp_request * request);
    int (*post_connect)           (gftp_request * request);
    void (*disconnect)            (gftp_request * request);
    off_t (*get_file)             (gftp_request * request, 
                                   const char *filename, 
                                   off_t startsize);
    int (*put_file)           (gftp_request * request, 
                               const char *filename, 
                               off_t startsize,
                               off_t totalsize );
    off_t (*transfer_file)        ( gftp_request * fromreq, 
                                    const char *fromfile, 
                                    off_t fromsize, 
                                    gftp_request * toreq, 
                                    const char *tofile, 
                                    off_t tosize );
    ssize_t (*get_next_file_chunk)    ( gftp_request * request, 
                                        char *buf, 
                                        size_t size );
    ssize_t (*put_next_file_chunk)    ( gftp_request * request, 
                                        char *buf, 
                                        size_t size );
    int (*end_transfer)           ( gftp_request * request );
    int (*abort_transfer)         ( gftp_request * request );
    int (*stat_filename)          ( gftp_request * request,
                                    const char *filename,
                                    mode_t * mode,
                                    off_t * filesize );
    int (*list_files)             ( gftp_request * request );
    int (*get_next_file)          ( gftp_request * request, 
                                    gftp_file *fle, 
                                    int fd );
    ssize_t (*get_next_dirlist_line)  ( gftp_request * request, 
                                        int fd,
                                        char *buf,
                                        size_t buflen );
    off_t (*get_file_size)        ( gftp_request * request, 
                                    const char *filename );
    int (*chdir)              ( gftp_request * request, 
                                const char *directory );
    int (*rmdir)              ( gftp_request * request, 
                                const char *directory );
    int (*rmfile)             ( gftp_request * request, 
                                const char *filename );
    int (*mkdir)              ( gftp_request * request, 
                                const char *directory );
    int (*rename)             ( gftp_request * request, 
                                const char *oldname, 
                                const char *newname );
    int (*chmod)              ( gftp_request * request, 
                                const char *filename, 
                                mode_t mode );
    int (*set_file_time)          ( gftp_request * request, 
                                    const char *filename, 
                                    time_t datettime );
    int (*site)               ( gftp_request * request, 
                                int specify_site,
                                const char *filename );
    int (*parse_url)          ( gftp_request * request,
                                const char *url );
    int (*set_config_options)     ( gftp_request * request );
    void (*swap_socks)            ( gftp_request * dest,
                                    gftp_request * source );


    /* set by config routines */
    char *email;
    int  passive_transfer : 1;
    int  ascii_transfers  : 1;
    int  ignore_pasv_address : 1;
    int  show_hidden_files : 1;
    int  resolve_symlinks  : 1;

    int  network_timeout;

#ifdef USE_SSL
    SSL * ssl;
#endif

    GIConv iconv_to, iconv_from; 
    unsigned int iconv_from_initialized : 1,
                 iconv_to_initialized : 1;
    char *iconv_charset;
};


gftp_request* gftp_request_new        (gftp_logging_func log_func);
void          gftp_request_destroy    (gftp_request *request, int free_request);

/* set up routines */
int  gftp_request_parse_url    (gftp_request *request, const char *url);
void gftp_request_set_hostname (gftp_request *request, const char *hostname);
void gftp_request_set_username (gftp_request *request, const char *username);
void gftp_request_set_password (gftp_request *request, const char *password);
void gftp_request_set_account  (gftp_request *request, const char *account);
void gftp_request_set_port     (gftp_request *request, unsigned int port);
int  gftp_request_set_directory(gftp_request *request, const char *directory);
void gftp_request_setup_startup_directory (gftp_request *request, 
                                           const char *option_name);

/* connection and disconnection */
int  gftp_request_connect      (gftp_request *request);
int  gftp_request_is_connected (gftp_request *request);
void gftp_request_disconnect   (gftp_request *request);
int  gftp_request_abort_transfer (gftp_request *request);


/* transfer */
off_t   gftp_request_get_file (gftp_request *request, const char *filename,
                               off_t startsize);
int     gftp_request_put_file  (gftp_request *request, const char *filename,
                                off_t startsize, off_t totalsize);
ssize_t gftp_request_get_next_file_chunk (gftp_request *request, 
                                          char *buf, size_t size);
ssize_t gftp_request_put_next_file_chunk (gftp_request * request, 
                                          char *buf, size_t size);
int  gftp_request_end_transfer   (gftp_request *request);

int  gftp_request_list_files_begin (gftp_request *request);
int  gftp_request_list_files_next  (gftp_request * request, const char *filespec,
                                    gftp_file * fle);

/* file operation */
int gftp_request_remove_directory (gftp_request *request, const char *directory);
int gftp_request_make_directory   (gftp_request *request, const char *directory);

int gftp_request_remove_file      (gftp_request *request, const char *file);
int gftp_request_rename_file      (gftp_request *request, const char *oldname,
                                   const char *newname);


int   gftp_request_stat_filename (gftp_request * request, const char *filename, 
                                  mode_t * mode, off_t * filesize);
off_t gftp_request_get_file_size (gftp_request * request, const char *filename);

int   gftp_request_chmod         (gftp_request *request, const char *file, 
                                  mode_t mode);
int   gftp_request_set_file_time (gftp_request *request, const char *file, 
                                  time_t datetime);
int   gftp_request_site_cmd      (gftp_request *request, int specify_site, 
                                  const char *command);

#endif
